﻿using System.Text.Json;
using System.Text.Json.Serialization;

namespace Sage.JsonConverters
{
    public static partial class SafeJsonConverters
    {
        /// <summary>
        /// 安全的多类型转布尔值转换器
        /// 支持多种布尔值表示形式：
        /// - 标准布尔值：true/false
        /// - 数字：任何非零数字为true，0为false，NaN/Infinity为false
        /// - 字符串：true/false、yes/no、on/off、y/n、1/0
        /// - 空值处理：空字符串、null返回false
        /// 绝对不会抛出异常，未知格式返回false
        /// </summary>
        public sealed class SafeBoolConverter : JsonConverter<bool>
        {
            /// <summary>
            /// 从JSON读取器中安全地读取布尔值
            /// </summary>
            /// <param name="reader">JSON读取器</param>
            /// <param name="typeToConvert">要转换的类型</param>
            /// <param name="options">序列化选项</param>
            /// <returns>安全转换后的布尔值，未知格式返回false</returns>
            public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
            {
                return reader.TokenType switch
                {
                    JsonTokenType.True => true,
                    JsonTokenType.False => false,
                    JsonTokenType.Number => TryGetNumberAsBool(ref reader),
                    JsonTokenType.String => ParseBooleanStringSafely(reader.GetString()),
                    JsonTokenType.Null or _ => false
                };
            }

            /// <summary>
            /// 将布尔值写入JSON写入器
            /// </summary>
            /// <param name="writer">JSON写入器</param>
            /// <param name="value">要写入的布尔值</param>
            /// <param name="options">序列化选项</param>
            public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options)
            {
                writer.WriteBooleanValue(value);
            }

            /// <summary>
            /// 安全地从JSON数字获取布尔值，处理所有数值类型和特殊值
            /// </summary>
            /// <param name="reader">JSON读取器</param>
            /// <returns>转换后的布尔值，非零为true，零为false，特殊值为false</returns>
            private static bool TryGetNumberAsBool(ref Utf8JsonReader reader)
            {
                try
                {
                    if (reader.TryGetInt32(out var intValue))
                        return intValue != 0;

                    if (reader.TryGetInt64(out var longValue))
                        return longValue != 0;

                    if (reader.TryGetDecimal(out var decimalValue))
                        return decimalValue != 0;

                    if (reader.TryGetDouble(out var doubleValue))
                        return doubleValue != 0.0 && !double.IsNaN(doubleValue) && !double.IsInfinity(doubleValue);

                    return false;
                }
                catch
                {
                    return false;
                }
            }

            /// <summary>
            /// 安全地解析字符串为布尔值，支持多种布尔表示形式
            /// </summary>
            /// <param name="value">要解析的字符串</param>
            /// <returns>解析后的布尔值，未知格式返回false</returns>
            private static bool ParseBooleanStringSafely(string? value)
            {
                if (string.IsNullOrWhiteSpace(value))
                    return false;

                return value.Trim().ToLowerInvariant() switch
                {
                    "true" or "1" or "yes" or "on" or "y" => true,
                    "false" or "0" or "no" or "off" or "n" or "" => false,
                    _ => false
                };
            }
        }

        /// <summary>
        /// 安全的可空布尔值转换器
        /// 与SafeBoolConverter类似，但空值和未知格式返回null而不是false
        /// 适合需要区分"未设置"和"false"的场景
        /// </summary>
        public sealed class SafeNullableBoolConverter : JsonConverter<bool?>
        {
            /// <summary>
            /// 从JSON读取器中安全地读取可空布尔值
            /// </summary>
            /// <param name="reader">JSON读取器</param>
            /// <param name="typeToConvert">要转换的类型</param>
            /// <param name="options">序列化选项</param>
            /// <returns>安全转换后的可空布尔值</returns>
            public override bool? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
            {
                return reader.TokenType switch
                {
                    JsonTokenType.Null => null,
                    JsonTokenType.True => true,
                    JsonTokenType.False => false,
                    JsonTokenType.Number => TryGetNumberAsBool(ref reader),
                    JsonTokenType.String when string.IsNullOrWhiteSpace(reader.GetString()) => null,
                    JsonTokenType.String => ParseBooleanStringSafely(reader.GetString()),
                    _ => null
                };
            }

            /// <summary>
            /// 将可空布尔值写入JSON写入器
            /// </summary>
            /// <param name="writer">JSON写入器</param>
            /// <param name="value">要写入的可空布尔值</param>
            /// <param name="options">序列化选项</param>
            public override void Write(Utf8JsonWriter writer, bool? value, JsonSerializerOptions options)
            {
                if (value.HasValue)
                    writer.WriteBooleanValue(value.Value);
                else
                    writer.WriteNullValue();
            }

            /// <summary>
            /// 安全地从JSON数字获取可空布尔值，处理所有数值类型和特殊值
            /// </summary>
            /// <param name="reader">JSON读取器</param>
            /// <returns>转换后的可空布尔值，特殊值返回null</returns>
            private static bool? TryGetNumberAsBool(ref Utf8JsonReader reader)
            {
                try
                {
                    if (reader.TryGetInt32(out var intValue))
                        return intValue != 0;

                    if (reader.TryGetInt64(out var longValue))
                        return longValue != 0;

                    if (reader.TryGetDecimal(out var decimalValue))
                        return decimalValue != 0;

                    if (reader.TryGetDouble(out var doubleValue))
                    {
                        if (double.IsNaN(doubleValue) || double.IsInfinity(doubleValue))
                            return null;
                        return doubleValue != 0.0;
                    }

                    return null;
                }
                catch
                {
                    return null;
                }
            }

            /// <summary>
            /// 安全地解析字符串为可空布尔值，支持多种布尔表示形式
            /// </summary>
            /// <param name="value">要解析的字符串</param>
            /// <returns>解析后的可空布尔值，未知格式返回null</returns>
            private static bool? ParseBooleanStringSafely(string? value)
            {
                if (string.IsNullOrWhiteSpace(value))
                    return null;

                return value.Trim().ToLowerInvariant() switch
                {
                    "true" or "1" or "yes" or "on" or "y" => true,
                    "false" or "0" or "no" or "off" or "n" => false,
                    _ => null
                };
            }
        }
    }
}